package cn.xorange.commons.file.service;

import cn.xorange.commons.file.configuration.FileConfig;
import cn.xorange.commons.file.configuration.QiNiuConfig;;
import cn.xorange.commons.file.entity.FileCode;
import cn.xorange.commons.file.exception.UploadException;
import cn.xorange.commons.file.utils.FileUtil;
import cn.xorange.commons.utils.id.IdUtils;
import com.alibaba.fastjson2.JSON;
import com.qiniu.common.QiniuException;
import com.qiniu.http.Response;
import com.qiniu.storage.model.DefaultPutRet;
import com.qiniu.util.Auth;
import com.qiniu.util.StringMap;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

@Slf4j
@Service
public class QiNiuUploadService {

    @Resource
    QiNiuConfig config;

    @Resource
    Auth auth;

    @Resource
    FileConfig fileConfig;

    //定义七牛云上传相关策略
    private StringMap putPolicy;

    /**
     * 以流的形式上传
     */
    public String uploadFile(String path, File file) throws UploadException {
        String fileName = file.getName();// file.getOriginalFilename();
        boolean check = FileUtil.checkValidFilename(fileName);
        if(Boolean.FALSE.equals(check)){
            throw UploadException.exception(FileCode.FILE_NAME_EXCEPTION);
        }
        String suffix = fileName.substring(fileName.lastIndexOf("."));
        //生成随机文件名
        fileName = IdUtils.fastSimpleUUID() + suffix;
        // 上传完整路径和文件名
        String filePath = FileUtil.getUploadPath(path) + fileName;
        try{
            String qiNiuToken = this.auth.uploadToken(fileConfig.qiniuProperties().getBucketName(), null, 3600, putPolicy);

            //InputStream inputStream =  file.getInputStream();
            FileInputStream fis = new FileInputStream(file);
            Response response = this.config.uploadManager().put(fis, filePath, qiNiuToken, null, null);
            int retry = 0;
            while (response.needRetry() && retry < 3) {
                response = this.config.uploadManager().put(fis, filePath, qiNiuToken, null, null);
                retry++;
            }
            //解析结果
            DefaultPutRet putRet = JSON.parseObject(response.bodyString(), DefaultPutRet.class);
            String returnPath = putRet.key;
            log.info("文件名称={}", returnPath);

            return this.fileConfig.bucketName() + "/"+ returnPath;
        }catch (QiniuException e){
            throw UploadException.qiNiuException(e);
        } catch (IOException e) {
            throw UploadException.ioException(e);
        }

    }



    /**
     * 删除七牛云上的相关文件
     * @param key
     * return
     */
    public void delFile(String key) throws UploadException {
        try {
            key = key.substring(this.fileConfig.qiniuProperties().getBucketName().length() + 1);
            Response response = this.config.bucketManager().delete(this.fileConfig.qiniuProperties().getBucketName(), key);
            int retry = 0;
            while (response.needRetry() && retry++ < 3) {
                response = this.config.bucketManager().delete(this.fileConfig.qiniuProperties().getBucketName(), key);
            }
        }catch (QiniuException e){
            throw UploadException.qiNiuException(e);
        }
    }

    public String getUrl(String path) throws UploadException{
        if(path.startsWith(fileConfig.qiniuProperties().getBucketName())) {
            return path.replace(this.fileConfig.qiniuProperties().getBucketName(), this.fileConfig.qiniuProperties().getDomain());
        }else {
            throw UploadException.exception(FileCode.FILE_OSS_NOT_FOUND);
        }
    }


    public void afterPropertiesSet() {
        this.putPolicy = new StringMap();
        putPolicy.put("returnBody", "{\"key\":\"$(key)\",\"hash\":\"$(etag)\",\"bucket\":\"$(bucket)\",\"width\":$(imageInfo.width), \"height\":${imageInfo.height}}");
        // 自定义文件名字
        // putPolicy.put("saveKey", UUID.randomUUID().timestamp());
    }


}
